package biz

import (
	"context"
	"time"

	"github.com/go-kratos/kratos/v2/errors"
	"github.com/go-kratos/kratos/v2/log"
	"gorm.io/gorm"

	pb "gitee.com/danqingzhao/go-dango/api/user/permission/v1"
	"gitee.com/danqingzhao/go-dango/pkg/common/core"
	"gitee.com/danqingzhao/go-dango/pkg/proto/settings"
	"gitee.com/danqingzhao/go-dango/pkg/third/orm"
)

type PermissionModel struct {
	Id        uint32         `gorm:"column:id;primary_key;AUTO_INCREMENT;comment:编号" json:"id"`
	CreatedAt time.Time      `gorm:"column:create_time;comment:创建时间" json:"created_at"`
	UpdatedAt time.Time      `gorm:"column:update_time;comment:修改时间" json:"updated_at"`
	DeleteAt  gorm.DeletedAt `gorm:"column:delete_at;type:boolean;comment:是否删除" json:"delete_at"`
	GrpcUrl   string         `gorm:"column:grpc_url;type:varchar(150);not null;uniqueIndex;comment:GRPC的URL地址" json:"grpc_url"`
	HttpUrl   string         `gorm:"column:http_url;type:varchar(150);index:idx_member;comment:HTTP的URL地址" json:"http_url"`
	Method    int32          `gorm:"column:method;type:varchar(20);index:idx_member;comment:请求方法" json:"method"`
	AppName   string         `gorm:"column:app_name;type:varchar(50);not null;comment:应用名称" json:"app_name"`
	IsActive  bool           `gorm:"column:is_active;type:boolean;comment:是否激活" json:"is_active"`
	Descr     string         `gorm:"column:descr;type:varchar(254);comment:描述" json:"descr"`
}

func (m *PermissionModel) TableName() string {
	return "user_permission"
}

type PermissionRepo interface {
	CreateModel(context.Context, *PermissionModel) error
	UpdateModel(context.Context, PermissionModel, ...any) error
	DeleteModel(context.Context, ...any) error
	FindModel(context.Context, []string, ...any) (*PermissionModel, error)
	ListModel(context.Context, orm.QueryParams) (int64, []PermissionModel, error)
}

type PermissionUsecase struct {
	log      *log.Helper
	permRepo PermissionRepo
}

func NewPermissionUsecase(
	logHelpers *settings.LogHelpers,
	permRepo PermissionRepo,
) *PermissionUsecase {
	return &PermissionUsecase{
		log:      logHelpers.Biz,
		permRepo: permRepo,
	}
}

func (uc *PermissionUsecase) CreatePermission(
	ctx context.Context,
	m PermissionModel,
) (*PermissionModel, *errors.Error) {
	if err := uc.permRepo.CreateModel(ctx, &m); err != nil {
		rErr := core.NewGormError(err, pb.ErrorReason_PERMISSION_CREATE_FAILED.String(), nil)
		uc.log.WithContext(ctx).Error(rErr.Error())
		return nil, rErr
	}
	return &m, nil
}

func (uc *PermissionUsecase) UpdatePermissionById(
	ctx context.Context,
	permId uint32,
	m PermissionModel,
) (*PermissionModel, *errors.Error) {
	if err := uc.permRepo.UpdateModel(ctx, m, "id = ?", permId); err != nil {
		rErr := core.NewGormError(err, pb.ErrorReason_PERMISSION_UPDATE_FAILED.String(), core.GenerateTempDataByID(permId))
		uc.log.WithContext(ctx).Error(rErr.Error())
		return nil, rErr
	}
	return uc.FindPermissionById(ctx, permId)
}

func (uc *PermissionUsecase) DeletePermissionById(
	ctx context.Context,
	permId uint32,
) *errors.Error {
	if err := uc.permRepo.DeleteModel(ctx, permId); err != nil {
		rErr := core.NewGormError(err, pb.ErrorReason_PERMISSION_DELETE_FAILED.String(), core.GenerateTempDataByID(permId))
		uc.log.WithContext(ctx).Error(rErr.Error())
		return rErr
	}
	return nil
}

func (uc *PermissionUsecase) FindPermissionById(
	ctx context.Context,
	permId uint32,
) (*PermissionModel, *errors.Error) {
	m, err := uc.permRepo.FindModel(ctx, nil, permId)
	if err != nil {
		rErr := core.NewGormError(err, pb.ErrorReason_PERMISSION_FIND_FAILED.String(), core.GenerateTempDataByID(permId))
		uc.log.WithContext(ctx).Error(rErr.Error())
		return nil, rErr
	}
	return m, nil
}

func (uc *PermissionUsecase) ListPermission(
	ctx context.Context,
	page, size int,
	query map[string]any,
) (int64, []PermissionModel, *errors.Error) {
	qp := orm.QueryParams{
		Preloads: []string{},
		Query:    query,
		OrderBy:  []string{"id"},
		Limit:    max(size, 0),
		Offset:   max(page-1, 0),
		IsCount:  true,
	}
	count, ms, err := uc.permRepo.ListModel(ctx, qp)
	if err != nil {
		rErr := core.NewGormError(err, pb.ErrorReason_PERMISSION_LIST_FAILED.String(), nil)
		uc.log.WithContext(ctx).Error(rErr.Error())
		return 0, nil, rErr
	}
	return count, ms, nil
}
